home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mint96sb.zoo / doc / fifo.doc < prev    next >
Encoding:
Text File  |  1992-10-18  |  7.6 KB  |  256 lines

  1. Using Fifo's:
  2.  
  3. Fifo's (first-in first-out pipes) are actually very easy to
  4. use. Here are a couple of things to keep in mind:
  5.  
  6. (1) The server program (the one that's going to be listening
  7.     for requests from clients) should create the fifo with
  8.     Fcreate(). The file descriptor returned from Fcreate is
  9.     the "server" descriptor; descriptors returned by Fopen will
  10.     be "client" descriptors. Data written to the server descriptor
  11.     can be read by client descriptors, and vice-versa.
  12. (2) Fifos are by default bidirectional. You can create a single
  13.     directional fifo by creating the fifo "read only"; in this case,
  14.     only the server descriptor can be written to, and only client
  15.     descriptors can be read from.
  16. (3) Be careful not to mix data up; if two clients are trying to
  17.     read from the same fifo at the same time, they each may read
  18.     data intended for the other. The easiest way to avoid this is
  19.     by having every client lock the fifo before accessing it,
  20.     and unlock the fifo when finished. It's also possible (if you're
  21.     careful) to use the fact that all writes of <1024 bytes are atomic
  22.     (i.e. take place in one "chunk") to avoid interleaving of data;
  23.     but locks are probably safer.
  24.  
  25. The flags to the Fcreate() system call used to create the fifo can
  26. be used to control the way the fifo works. For most applications,
  27. the flags should probably be 0, i.e. the call should look like
  28.    serverfd = Fcreate("U:\\PIPE\\FIFO", 0);
  29. but for some specialized applications it may be useful to use one
  30. or more of the following flags (they may be or'd together:
  31.  
  32. FA_RDONLY: Make the fifo unidirectional; the server fd will be write
  33.     only, and the client fd read only.
  34. FA_HIDDEN: Make reads from the fifo return "end of file" if no other
  35.     process has the fifo open for writing. This is normally not desired
  36.     for server processes, since the server's read will often occur
  37.     when nobody has the fifo open, and should wait until some client
  38.     does want to use the fifo.
  39. FA_SYSTEM: Make the fifo a "pseudo-terminal". This type of fifo behaves
  40.     just like a terminal, and most of the terminal control Fcntl calls
  41.     can operate on it. Also, data can be passed through the fifo in long
  42.     words rather than in bytes, if the Fputchar() system call is used.
  43.     This allows the server program to pass the extended BIOS information
  44.     (such as the shift key status and scan code) to be returned by Bconin()
  45.     calls on the client side of the pipe. The 'extra' 3 bytes of the longword
  46.     could also be used for other out of band data as well.
  47. FA_CHANGED: Make the fifo return from an Fread() call as soon as any data are
  48.     available (just like a terminal). This isn't necessary if the FA_SYSTEM
  49.     bit is set (since pseudo-terminals already act like terminals), but is
  50.     useful for making ordinary fifo's emulate Unix pipe semantics.
  51.  
  52. Here is a sample pair of applications. The server program ("fortserv.c")
  53. creates a fifo and listens on it for requests. When it receives a
  54. request, it writes a cute saying (a "fortune cookie") back to the fifo.
  55. The client program ("fortune.c") opens the fifo, writes a request,
  56. reads the response, and prints the result on the terminal. These are
  57. very simple minded applications, but it should give you an idea of
  58. the flavour of how to use fifos for interprocess communication.
  59. -------------------------- fortserv.c -------------------------
  60. /* fortune server: send cookies to clients */
  61. /* illustrates server side use of fifos */
  62.  
  63. /*
  64.  * This program opens a fifo ("U:\PIPE\FORTUNE")
  65.  * and listens to requests on that fifo. When it
  66.  * gets a request (consisting of a single '?'
  67.  * character) it writes back as a reply a 1 byte
  68.  * "length" followed by a randomly selected saying.
  69.  * BUGS:
  70.  *   - maximum of 255 characters for a fortune
  71.  *   - the fortunes aren't particularly interesting
  72.  */
  73.  
  74. #ifdef __GNUC__
  75. #include <minimal.h>
  76. #endif
  77. #include <osbind.h>
  78. #include <mintbind.h>
  79. #include <string.h>
  80.  
  81. #define FIFONAME "U:\\PIPE\\FORTUNE"
  82. #define MAXSIZE 255
  83.  
  84. /* witty (?) sayings */
  85.  
  86. char * sayings[] = {
  87. "Core fault -- program dumped.",
  88. "Don't worry, be happy!",
  89. "Help! I'm trapped in a fortune cookie factory!",
  90. "\"Home is where you wear-a your hat.\"",
  91. "I want a cookie.",
  92. "MS-DOS: just say \"no\".",
  93. "Never play leapfrog with a unicorn.",
  94. "No matter where you go, there you are.",
  95. "Sorry, I'm out of short, pithy sayings today.\r\nTry again later.",
  96. "They say that playing NetHack is like walking into a death trap.",
  97. "Vision hazy, try again later.",
  98. "What? You expected something funny?",
  99. "Why is it that UFO's always seem to visit idiots?",
  100. "Your puny intellect is no match for our superior weapons.",
  101. };
  102. #define NUMSAYINGS (sizeof(sayings) / sizeof(char *))
  103.  
  104. /* file descriptor for the fortune fifo */
  105. int fd;
  106.  
  107.  
  108. /* send a witty saying out through the fifo */
  109.  
  110. void
  111. send_saying()
  112. {
  113.     int i;
  114.     char *s;
  115.     char tmpbuf[MAXSIZE+1];
  116.  
  117. /* pick a saying at random */
  118.     i = ((unsigned)Random() >> 1) % NUMSAYINGS;
  119.     s = sayings[i];
  120.  
  121. /* construct the message to send */
  122.     i = (int)strlen(s);
  123.     tmpbuf[0] = i;
  124.     strcpy(tmpbuf+1,s);
  125.  
  126. /* we really should check for an error */
  127.     (void)Fwrite(fd, (long)i+1, tmpbuf);
  128. }
  129.  
  130. /* main function: create the fifo, then sit around
  131.  * listening for requests
  132.  */
  133.  
  134. int
  135. main(argc, argv, envp)
  136.     int argc;
  137.     char **argv, **envp;
  138. {
  139.     char c;
  140.     long r;
  141.  
  142.     fd = Fcreate(FIFONAME, 0);
  143.     if (fd < 0) {
  144.         Cconws("Couldn't create ");
  145.         Cconws(FIFONAME);
  146.         Cconws("!\r\n");
  147.         Pterm(1);
  148.     }
  149.  
  150.     for(;;) {
  151.         r = Fread(fd, 1L, &c);
  152.         if (r != 1) {    /* read error?? */
  153.             break;
  154.         }
  155.         if (c == '?') {    /* request for saying */
  156.             send_saying();
  157.         }
  158.     /* could have other requests here */
  159.     }
  160.     return 0;
  161. }
  162. ------------------------ fortune.c ----------------------
  163. /* fortune client: get a fortune cookie from
  164.  * the fortune server
  165.  */
  166.  
  167. /* illustrates client side use of fifos */
  168.  
  169. #ifdef __GNUC__
  170. #include <minimal.h>
  171. #endif
  172. #include <osbind.h>
  173. #include <mintbind.h>
  174.  
  175. #define FIFONAME "U:\\PIPE\\FORTUNE"
  176. #define BUFSIZ 256
  177. #define F_SETLKW 7
  178.  
  179. struct flock {
  180.     short l_type;            /* type of lock */
  181. #define F_RDLCK        0
  182. #define F_WRLCK        1
  183. #define F_UNLCK        3
  184.     short l_whence;            /* SEEK_SET, SEEK_CUR, SEEK_END */
  185.     long l_start;            /* start of locked region */
  186.     long l_len;            /* length of locked region */
  187.     short l_pid;            /* pid of locking process
  188.                         (F_GETLK only) */
  189. };
  190.  
  191. int
  192. main(argc, argv, envp)
  193.     int argc;
  194.     char **argv, **envp;
  195. {
  196.     int fd;
  197.     char buf[BUFSIZ];
  198.     unsigned char len;
  199.     struct flock lock;
  200.     long r;
  201.  
  202. /* open the fifo */
  203.     fd = Fopen(FIFONAME, 2);
  204.     if (fd < 0) {
  205.         Cconws("Couldn't open ");
  206.         Cconws(FIFONAME);
  207.         Cconws("!\r\n");
  208.         Pterm(1);
  209.     }
  210.  
  211. /* get a lock; this makes sure that two fortune
  212.  * programs don't try to send requests and read
  213.  * replys at the same time
  214.  */
  215.  
  216.     lock.l_type = F_WRLCK;
  217.  
  218. /* lock the whole file -- only thing that makes sense
  219.  * for a fifo
  220.  */
  221.     lock.l_whence = 0;
  222.     lock.l_start = lock.l_len = 0L;
  223.  
  224.     r = Fcntl(fd, &lock, F_SETLKW);
  225.     if (r != 0) {
  226.         Cconws("Couldn't get a lock!\r\n");
  227.         Pterm(r);
  228.     }
  229.  
  230. /* write the request */
  231.     Fwrite(fd, 1L, "?");
  232. /* wait for a reply */
  233. /* the fortune server writes a 1 byte length, followed by
  234.  * the fortune itself
  235.  */
  236.     r = Fread(fd, 1L, &len);
  237.     if (r != 1L || len != Fread(fd, (long)len, buf)) {
  238.         Cconws("Error reading fortune!\r\n");
  239.         Pterm(1);
  240.     }
  241.     buf[len] = 0;
  242.  
  243. /* unlock the fifo */
  244.  
  245.     lock.l_type = F_UNLCK;
  246.     (void) Fcntl(fd, &lock, F_SETLKW);
  247.  
  248.     Fclose(fd);
  249.  
  250. /* now write the fortune to the screen */
  251.     Cconws(buf);
  252.     Cconws("\r\n");
  253.  
  254.     return 0;
  255. }
  256.